﻿using System.Dns.Toolkit.DnsServer;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace DnsServer.TestUnit
{
    
    
    /// <summary>
    ///This is a test class for PriorityQueueTest and is intended
    ///to contain all PriorityQueueTest Unit Tests
    ///</summary>
    [TestClass()]
    public class PriorityQueueTest {


        /// <summary>
        ///A test for Enqueue
        ///</summary>
        [TestMethod]
        public void EnqueueTest1() {
            var pq = new PriorityQueue<int, string>();
            pq.Enqueue(1, "priority 1.0");
            pq.Enqueue(2, "priority 2.0");
            pq.Enqueue(3, "priority 3.0");
            pq.Enqueue(1, "priority 1.1");

            string s;
            bool b;

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 1.0", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 1.1", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 2.0", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 3.0", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual(false, b);


        }



        /// <summary>
        ///A test for Enqueue
        ///</summary>
        [TestMethod]
        public void EnqueueTest3() {
            var pq = new PriorityQueue<int, string>();
            Assert.AreEqual(true, pq.IsEmpty);

            pq.Enqueue(1, "priority 1.0");
            Assert.AreEqual(false, pq.IsEmpty);

            string s;
            bool b;

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 1.0", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual(false, b);


        }
        /// <summary>
        ///A test for Enqueue
        ///</summary>
        [TestMethod]
        public void EnqueueTest2() {
            var pq = new PriorityQueue<int, string>();
            pq.Enqueue(1, "priority 1.0");
            pq.Enqueue(2, "priority 2.0");
            pq.Enqueue(3, "priority 3.0");
            pq.Enqueue(1, "priority 1.1");

            string s;
            bool b;

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 1.0", s);
            Assert.AreEqual(true, b);
            
            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 1.1", s);
            Assert.AreEqual(true, b);
            
            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 2.0", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual("priority 3.0", s);
            Assert.AreEqual(true, b);

            b = pq.TryDequeue(out s);
            Assert.AreEqual(false, b);
            

        }

        /// <summary>
        ///A test for Enqueue
        ///</summary>
        [TestMethod]
        public void EnqueueTest4() {

            var pq = new PriorityQueue<int, string>();
            var r = new Random();

            ThreadPool.QueueUserWorkItem(
                o => {
                    pq = (PriorityQueue<int, string>)o;
                    int priority = r.Next(10);
                    pq.Enqueue(priority, string.Format("{0}", priority));
                },
                pq
            );

            ThreadPool.QueueUserWorkItem(
                o => {
                    pq = (PriorityQueue<int, string>)o;
                    string s;
                    if (pq.TryDequeue(out s)) {
                        Console.WriteLine("{0}", s);
                    }
                },
                pq
            );

            Thread.Sleep(100);

            Assert.AreEqual(true, pq.IsEmpty);
        }


        /// <summary>
        ///A test for Enqueue
        ///</summary>
        [TestMethod]
        public void EnqueueTest5() {

            var pq = new PriorityQueue<int, string>();
            var r = new Random();
            var c = 0;

            for (int i = 0; i < 10000; i++) {

                ThreadPool.QueueUserWorkItem(
                    o => {
                        pq = (PriorityQueue<int, string>) o;
                        int priority = r.Next(10);
                        pq.Enqueue(priority, string.Format("{0}", priority));
                        Console.WriteLine("E{0}", priority);
                        Interlocked.Increment(ref c);
                    },
                    pq
                    );

                ThreadPool.QueueUserWorkItem(
                    o => {
                        pq = (PriorityQueue<int, string>) o;
                        string s;
                        if (pq.TryDequeue(out s)) {
                            Console.WriteLine("D{0}", s);
                        }
                        Interlocked.Decrement(ref c);
                    },
                    pq
                    );

            }
            Thread.Sleep(0);

            Assert.AreEqual(true, pq.IsEmpty);
            Assert.AreEqual(0, c);
        }


    }


}
